package logs

import (
	"fmt"
	"goadmin/config"
	"os"
	"path/filepath"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

var (
	logger *zap.Logger
	sugar  *zap.SugaredLogger
)

// 自定义时间格式
func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString(t.Format("2006/01/02 15:04:05"))
}

// InitLogger 初始化 logger（只允许调用一次）
func InitLogger() {
	logDir := config.Logs.LogDir
	if err := os.MkdirAll(logDir, 0755); err != nil {
		initDefaultLogger()
		return
	}

	// lumberjack 负责轮转
	//logFile := filepath.Join(logDir, "app.log") // 文件名固定，lumberjack 会自动加日期
	logFile := filepath.Join(logDir, time.Now().Format("2006-01-02")+".log")
	fmt.Println("logFile_______", logFile)
	w := zapcore.AddSync(&lumberjack.Logger{
		Filename:   logFile,
		MaxSize:    50, // MB
		MaxBackups: 30,
		MaxAge:     30,   // days
		LocalTime:  true, // 用本地时间命名
		Compress:   false,
	})

	// encoder 配置
	encCfg := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     customTimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}

	// 同时输出到文件和控制台
	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(encCfg),
		zapcore.NewMultiWriteSyncer(w, zapcore.AddSync(os.Stdout)),
		zap.InfoLevel,
	)

	logger = zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))
	sugar = logger.Sugar()
}

// 兜底默认 logger
func initDefaultLogger() {
	cfg := zap.NewDevelopmentConfig()
	cfg.OutputPaths = []string{"stdout"}
	var err error
	logger, err = cfg.Build()
	if err != nil {
		panic(fmt.Sprintf("failed to init default logger: %v", err))
	}
	sugar = logger.Sugar()
	sugar.Warn("using default logger config")
}

// Sync 刷新缓冲区
func Sync() {
	if logger != nil {
		_ = logger.Sync()
	}
}

// 全局快捷方法
func Info(msg string, fields ...zap.Field)  { logger.Info(msg, fields...) }
func Error(msg string, fields ...zap.Field) { logger.Error(msg, fields...) }
func Warn(msg string, fields ...zap.Field)  { logger.Warn(msg, fields...) }
func Sugar() *zap.SugaredLogger             { return sugar }
